package com.zrrd.jt_admin.manager.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zrrd.jt_admin.common.bo.RuleBo;
import com.zrrd.jt_admin.common.entity.Manager;
import com.zrrd.jt_admin.common.entity.Role;
import com.zrrd.jt_admin.common.entity.Rule;
import com.zrrd.jt_admin.common.utils.JwtUtils;
import com.zrrd.jt_admin.common.vo.ManagerLoginVo;
import com.zrrd.jt_admin.common.page.ManagerPageVo;
import com.zrrd.jt_admin.common.vo.ManagerVo;
import com.zrrd.jt_admin.common.bo.RoleBo;
import com.zrrd.jt_admin.manager.mapper.ManagerMapper;
import com.zrrd.jt_admin.manager.service.ManagerService;
import com.zrrd.jt_admin.manager.service.RoleService;
import com.zrrd.jt_admin.manager.service.RuleService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author WanJl
 * @version 1.0
 * @title ManagerServiceImpl
 * @description
 * @create 2024/6/25
 */
@Service
public class ManagerServiceImpl extends ServiceImpl<ManagerMapper, Manager> implements ManagerService {

    @Resource
    private ManagerMapper managerMapper;

    @Resource
    private RoleService roleService;

    @Resource
    private RuleService ruleService;

    @Resource
    private RedisTemplate redisTemplate;
    /**
     * 管理员账号登录
     *
     * @param username 用户名
     * @param password 密码
     * @return 管理员的整体信息
     */
    @Override
    public ManagerLoginVo login(String username, String password) {
        //分3步
        //1-根据用户名查询manager表，
        Manager manager = lambdaQuery().eq(Manager::getUsername, username).one();
        //判空
        if (manager == null) {
            return null;
        }

        //2-判断查询到的密码和用户输入的密码是否一致，不一致直接return
        //给password进行加密
        ///*******加密------
        //将从Controller层传入的password进行MD5加密
        //加密--  加盐加密  盐：
        String pwd = DigestUtils.md5DigestAsHex((password + JwtUtils.generalKey()).getBytes());

        //3-如果密码一致，说明登录成功，需要返回角色信息以及角色的权限列表
        if(manager.getPassword().equals(pwd)){

            ManagerLoginVo managerLoginVo = new ManagerLoginVo();
            BeanUtils.copyProperties(manager, managerLoginVo);
            //4-根据manager查到的角色id role_id。
            // 查询角色表，将查询到的角色信息，封装成Role对象，赋值给ManagerVo的role属性
            Role role = roleService.getById(manager.getRoleId());
            managerLoginVo.setRole(role);
            managerLoginVo.setRoleId(role.getId());
            //5-根据role_id查询当前角色对应的权限菜单列表，并且复制给ManagerVo的tree属性
            List<RuleBo> list = ruleService.getRuleListByRoleId(role.getId());
            managerLoginVo.setTree(list);
            System.out.println(list);

            //6-遍历权限菜单列表，拿出所有的菜单名称，封装成新的列表，并且复制给ManagerVo的ruleNames属性
            List<String> ruleNames = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                Rule rule = list.get(i);
                if (rule.getRuleId()!=0){
                    ruleNames.add(rule.getName());
                }
            }
            managerLoginVo.setRuleNames(ruleNames);

            //7-颁发token
            String token = JwtUtils.getToken(manager.getId().longValue());
            managerLoginVo.setToken(token);

            //把token存入到Redis中。
            Integer id = managerLoginVo.getId();
            //字符串方式
            redisTemplate.opsForValue().set("TOKEN:"+token, JSON.toJSONString(id));

            return managerLoginVo;
        }
        return null;
    }

    /**
     * 分页查询所有管理员信息
     *
     * @return
     */
    @Override
    public ManagerPageVo findByPage(Integer page, Integer limit, String keyword) {
        ManagerPageVo managerPageVo = new ManagerPageVo();
        //设置PageHelper的分页
        PageHelper.startPage(page, limit);
        //1-查询管理员信息列表
        //判断搜索关键字是否为空
        boolean blank = StringUtils.isNotBlank(keyword);
        List<Manager> list = lambdaQuery()
                .like(blank, Manager::getUsername, keyword)
                .list();
        //把查询到的集合封装到PageInfo里
        PageInfo<Manager> pageInfo = new PageInfo<>(list);
        /*
        QueryWrapper<Manager> wrapper = new QueryWrapper<>();
        wrapper.eq(blank,"username",mpq.getKeyword());
        wrapper.orderByDesc("create_time");
        List<Manager> list = list(wrapper);
        */
        List<Manager> managerList = pageInfo.getList();

        //2-遍历管理员信息列表，根据每个管理员信息role_id查询该管理员的角色信息

        List<ManagerVo> mvList = new ArrayList<>();
        for (Manager manager : managerList) {
            ManagerVo managerVo=new ManagerVo();
            Role role = roleService.getById(manager.getRoleId());
            //将一个对象里面的所有属性值，拷贝到另一个对象中的同名属性中
            BeanUtils.copyProperties(manager, managerVo);
            //3-将管理员信息和管理员的角色信息都封装进ManagerVo对象，再形成ManagerVo对象的集合
            managerVo.setRole(role);

            mvList.add(managerVo);
        }
        //4-将ManagerVo对象的集合封装进封装进ManagerPageVo的list属性
        managerPageVo.setList(mvList);

        //5-计算查询到的管理员信息列表长度，封装进ManagerPageVo的totalCount属性
        managerPageVo.setTotalCount(pageInfo.getTotal());
        //6-查询角色列表，封装进ManagerPageVo的totalCount属性roles

        List<Role> roleList = roleService.list();
        //传统方式操作
        /*
            List<RoleVo> roleVoList = new ArrayList<>();
            for (Role role : roleList) {
                RoleVo roleVo=new RoleVo();
                BeanUtils.copyProperties(role, roleVo);
                roleVoList.add(roleVo);
            }
        */
        //lambda的流式操作
        List<RoleBo> roleBoList = roleList.stream().map(role -> {   //role是遍历集合后的每一个元素对象
            //新建Vo对象
            RoleBo roleBo = new RoleBo();
            //复制属性
            BeanUtils.copyProperties(role, roleBo);
            //将Vo对象返回
            return roleBo;
            //通过.collect(Collectors.toList())封装成一个RoleVo对象的集合
        }).collect(Collectors.toList());

        managerPageVo.setRole(roleBoList);
        //7-返回ManagerPageVo
        return managerPageVo;
    }
}
